/*
 * Funny Language - a free style programming language.
 * Copyright (C) 2015 by fanguangping (fanguangping@163.com)
 * ds.c
 */

#include "ds.h"
#include "memory.h"
#include "../types/object.h"

//null safe implement
void init_constants() {
	(&g_nil)->_flag = REF_MARK;
	(&g_nil)->_type = NULL;
	(&g_nil)->_name = NULL;
	(&g_nil)->_pair._car = (&g_nil)->_pair._cdr = &g_nil;
	(&g_eof)->_flag = REF_MARK;
	(&g_eof)->_type = NULL;
	(&g_eof)->_name = NULL;
	(&g_eof)->_pair._car = (&g_nil)->_pair._cdr = &g_nil;
	(&g_true)->_flag = REF_MARK;
	(&g_true)->_type = BOOLEAN_TYPE;
	(&g_true)->_name = NULL;
	(&g_true)->_pair._car = (&g_true)->_pair._cdr = &g_true;
	(&g_false)->_flag = REF_MARK;
	(&g_false)->_type = BOOLEAN_TYPE;
	(&g_false)->_name = NULL;
	(&g_false)->_pair._car = (&g_false)->_pair._cdr = &g_false;
}

/*
 * 特征标记函数
 *
 * */

int is_atom(Scheme *sc, Cell *p) {
	if (type_of(sc, p, PAIR_TYPE))
		return FALSE;
	else
		return TRUE;
}

// 是否immutable
int is_immutable(Cell* p) {
	return (p->_flag) & REF_IMMUTABLE;
}

// 设为不可改变
void set_immutable(Cell* p) {
	p->_flag |= REF_IMMUTABLE;
}

// 是否mark
int is_mark(Cell* p) {
	return (p->_flag) & REF_MARK;
}

// 设置mark
void set_mark(Cell* p) {
	(p->_flag) |= REF_MARK;
}

// 清除mark
void clear_mark(Cell* p) {
	(p->_flag) &= ~REF_MARK;
}


/*
 * car/cdr/cons函数
 * */
Cell* car(Cell* p) {
	return p->_pair._car;
}

Cell* cdr(Cell* p) {
	return p->_pair._cdr;
}

Cell* cons(Scheme *sc, Cell* a, Cell* b) {
	return make_cell(sc, a, b);
}

Cell* immutable_cons(Scheme *sc, Cell* a, Cell* b) {
	Cell* x = make_cell(sc, a, b);
	set_immutable(x);
	return (x);
}
